(function(){
    var fGetFloatAcc = function(num){
        var t = 0;
        if(typeof num !== 'string'){
            num = num.toString();
        }
        // 失败时使用默认值 0
        try{ t = num.split('.')[1].length;}catch(e){}
        return t;
    };
    /**
     * @widoc $.dataFormat
     * @namespace aux
     * @depends encode/$.encodeHtml
     * @des 用于转换数据的公共库
     * @type object
     * @attr {function} arr2Hash(opts) 将 data 数组转为 hash 对象。
     *  - opts.data {Array} 原始数据
     *  - opts.keyField {string} 在 data 中的 keyField。data 中将作为 res 对象的 key 的字段。
     *  - opts.valField {string=} 在 data 中的 valField。定义时，res[key] = dataItem[valField]；未定义时，res[key] = dataItem(浅拷贝)。
     * @attr {function} hash2Arr(opts) 将 key-val 格式的数据转换为数组。
     *  - opts.data {object} 原始数据
     *  - opts.keyField {string=} 在 resItem 中的 keyField。定义时，resItem[keyField] = key。valField 未定义时失效。
     *  - opts.valField {string=} 在 resItem 中的 valField。定义时，resItem[valField] = data[key]；未定义时，resItem = data[key](浅拷贝)。
     * @attr {function} tree2Hash(opts) 将树结构数据转为 hash 对象。
     *  - opts.data {Array} 原始数据
     *  - opts.keyField {string=} 在 data 中的 keyField，将作为 res 对象的 key 的字段，默认为：'id'。
     *  - opts.pkeyField {string=} 在 data 中的 pkeyField，将在 res 的每一项中记录父节点 key，默认为：'pid'。
     *  - opts.chdField {string=} 在 data 中的 chdField。标识 data 中每个数据项中包含子节点数据的字段，默认为：'children'。
     * @attr {function} pureClone(src) 根据源对象深度拷贝数据，并删除 __ 开头的组件属性。
     * @attr {function} domStr(val) 将 val 转为在 dom 中显示的字符串。
     *  - val 若为 undefined | null，将被转为 ''，其他类型将转为 string 后，由 $.encodeHtml() 编码
     * @attr {function} isNumber(val) 判断是否是数字。
     *  - val number 且不是 NaN 时才返回 true
     * @attr {function} floatAdd(f1,f2) 浮点数计算：f1+f2。
     * @attr {function} floatSub(f1,f2) 浮点数计算：f1-f2。
     * @attr {function} floatMul(f1,f2) 浮点数计算：f1*f2。
     * @attr {function} floatDiv(f1,f2) 浮点数计算：f1/f2。
     */
    $.dataFormat = {
        arr2Hash: function(opts){
            opts = $.extend({
                data: [],
                keyField: undefined,
                valField: ''
            }, opts);
            var res = {},
                data = opts.data,
                sKeyField = opts.keyField,
                sValField = opts.valField;
            if(data){
                for(var i = 0, cur, len = data.length; i < len; i++){
                    cur = data[i];
                    res[cur[sKeyField]] =
                        sValField ? cur[sValField] : cur;
                }
            }
            return res;
        },
        hash2Arr: function(opts){
            opts = $.extend({
                data: {},
                keyField: '',// 定义时，resItem[keyField] = key
                valField: ''// 定义时，resItem[valField] = data[key]；未定义时，resItem = data[key](浅拷贝)
            }, opts);
            var res = [],
                data = opts.data,
                sKeyField = opts.keyField,
                sValField = opts.valField,
                cur, resItem;
            if(data){
                for(var k in data){
                    if(data.hasOwnProperty(k)){
                        cur = data[k];
                        if(sValField){
                            resItem = {};
                            resItem[sValField] = cur;
                        }
                        else{
                            resItem = cur;
                        }
                        if(sKeyField && typeof resItem === 'object'){
                            resItem[sKeyField] = k;
                        }
                        res.push(resItem);
                    }
                }
            }
            return res;
        },
        tree2Hash: function(opts){
            opts = $.extend({
                data: [],
                keyField: 'id',
                pkeyField: 'pid',// 节点中保存父节点 id 的字段
                chdField: 'children'
            }, opts);
            var aData = opts.data,
                oHashData = {};
            var sKeyField = 'id',
                sPkeyField = 'pid',
                sChdField = 'children';
            var fManageChd = function(dl, pid){// 直接追加 str
                for(var i = 0, id, cur, chd, len = dl.length; i < len; i++){
                    cur = dl[i];
                    id = cur[sKeyField];
                    if(!cur[sPkeyField] && pid){
                        cur[sPkeyField] = pid;
                    }
                    oHashData[id] = cur;
                    chd = cur[sChdField];// 有子节点
                    if(chd && chd.length){
                        fManageChd(chd, id);
                    }
                }
            };
            fManageChd(aData);
            return oHashData;
        },
        pureClone: function(data){// 根据源对象深度拷贝数据，并删除 __ 开头的组件属性
            var fClone = function(src){
                // 基本类型及 function
                if(typeof src !== 'object' || src === null) return src;
                var dst = Object.prototype.toString.call(src) === '[object Array]' ? [] : {};//判断参数的类型,定义要拷贝的对象的数据类型
                for(var i in src){
                    if(src.hasOwnProperty(i) && !/^__/.test(i)){
                        dst[i] = typeof src[i] === 'object' && src ? fClone(src[i]) : src[i];
                    }
                }
                return dst;
            };
            return fClone(data);
        },
        domStr: function(val){
            if(val === undefined || val === null){
                return '';
            }
            // 强转为字符串
            return $.encodeHtml(val + '');
        },
        /* number */
        isNumber: function(val){// 判断是否是数字类型，且非 NaN
            return typeof val === 'number' && !isNaN(val);
        },
        // 浮点数计算
        floatAdd: function(f1, f2){
            var acc = Math.max(fGetFloatAcc(f1), fGetFloatAcc(f2)),
                m = Math.pow(10, acc);// 计算结果的精度
            return ((f1 * m + f2 * m) / m);
        },
        floatSub: function(f1, f2){
            var acc = Math.max(fGetFloatAcc(f1), fGetFloatAcc(f2)),
                m = Math.pow(10, acc);// 计算结果的精度
            return ((f1 * m - f2 * m) / m);
        },
        floatMul: function(f1, f2){
            var acc1 = fGetFloatAcc(f1),
                acc2 = fGetFloatAcc(f2);
            return (f1 * Math.pow(10, acc1)) * (f2 * Math.pow(10, acc2)) / Math.pow(10, acc1 + acc2);
        },
        floatDiv: function(f1, f2){
            var acc1 = fGetFloatAcc(f1),
                acc2 = fGetFloatAcc(f2);
            return (f1 * Math.pow(10, acc1)) / (f2 * Math.pow(10, acc2)) * Math.pow(10, acc2 - acc1);
        },
        /* Date */
        // 与 Date.format() 相对
        str2Date: function(str, formatStr){
        },
        date2History: function(dt){
        },
        date2Future: function(dt){
        }
    };
})();